'''
Actor网络
根据当前状态计算当前输出（新参数）
Loss=actor的Q-critic的Q的均方差--->Loss = w1*loss(当前动作-目标动作)+w2*loss(LSTM)
Critic
根据当前状态计算当前输出（旧参数）
一段时间直接复制actor网络

LSTM
输入一系列状态+动作，维数a_list_dim, s_dim+a_dim，
暂定输出是当前状态：
loss=预测当前状态-实际当前状态


'''
import tensorflow as tf
import numpy as np
# # 模型超参数
# n_steps = 10  # 时间步数
# n_inputs = 1  # 输入特征数
# n_neurons = 100  # LSTM单元数量
# n_outputs = 1  # 输出特征数
# learning_rate = 0.001  # 学习率
# n_epochs = 100  # 训练次数
# batch_size = 50  # 批次大小
#
# # 数据准备
# # 构造一个正弦波数据集
# t_min, t_max = 0, 30
# resolution = 0.1
# t = np.linspace(t_min, t_max, int((t_max - t_min) / resolution))
# y = np.sin(t)
#
# # 将数据集转换成可以用于训练的数据格式
# X = []
# y_data = []
# for i in range(len(y) - n_steps):
#     # X数组中的每个元素都是一个形状为(n_steps, n_inputs)的输入样本矩阵。
#     X.append(y[i:i+n_steps].reshape(-1, n_inputs))
#     y_data.append(y[i+n_steps])
# X = np.array(X)
# y_data = np.array(y_data).reshape(-1, 1)

# 定义LSTM模型
class LSTM(object):
    def __init__(self,sess,n_steps,n_inputs,n_outputs,n_neurons,learning_rate):
        self.sess = sess
        self.n_steps = n_steps
        self.n_inputs = n_inputs
        self.n_outputs = n_outputs
        self.n_neurons = n_neurons
        self.learning_rate = learning_rate

        # n_inputs = s'_dim+a_dim
        self.X = tf.placeholder(tf.float32, [None, self.n_steps, self.n_inputs])
        self.X_list = tf.unstack(self.X, axis=1)  # 把LSTM模型的输入数据按时间步数展开
        # n_outputs=s_dim
        self.Y = tf.placeholder(tf.float32, [None, self.n_outputs])

        lstm_cell = tf.contrib.rnn.BasicLSTMCell(self.n_neurons, forget_bias=1.0)
        outputs, states = tf.contrib.rnn.static_rnn(lstm_cell, self.X_list, dtype=tf.float32) # tf.nn.dynamic_rnn
        # outputs第一个维度表示batch size，第二个维度表示时间步，第三个维度表示隐藏状态向量的维度
        # outputs 的长度为时间步数，每个元素是一个大小为 [batch_size, n_hidden] 的张量，代表 LSTM 模型在每个时间步的输出结果。
        # states 是一个元组，其中包含 LSTM 模型在最后一个时间步的状态，包括记忆细胞和隐藏状态，它们都是大小为 [batch_size, n_hidden] 的张量。
        output = outputs[-1]
        self.y_pred = tf.layers.dense(output, units=n_outputs)

        # 定义损失函数和优化器
        with tf.variable_scope('loss'):
            self.loss = tf.reduce_mean(tf.square(self.y_pred - self.Y))
        with tf.variable_scope('train'):
            self._train_op = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(self.loss)
        # 初始化
        init = tf.global_variables_initializer()
        self.sess.run(init)
    # def train(self,X_batch,y_batch):
    #     _, l = self.sess.run([self._train_op, self.loss], feed_dict={self.X: X_batch, self.Y: y_batch})
    #     return l